﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Modeling;

namespace Navigation.Designer
{
	internal static class NavigationUtility
	{
		internal static NavigationDiagram LoadModel(string navigationModel)
		{
			Store store = new Store(typeof(NavigationLanguageDomainModel));
			NavigationDiagram navigationConfiguration;
			using (Transaction t = store.TransactionManager.BeginTransaction())
			{
				navigationConfiguration = NavigationLanguageSerializationHelper.Instance.LoadModel(store, navigationModel, null, null, null);
				t.Commit();
			}
			return navigationConfiguration;
		}

		internal static bool ValidateNavigation(NavigationDiagram navigationConfiguration, List<Dialog> dialogs)
		{
			var unconvertedNavigations =
				from s in navigationConfiguration.States
				from su in s.Successors
				let c = GetStateWrappersCanNavigateTo(dialogs, s, su).Count()
				where (c > 0 && c < GetStateWrappers(dialogs, s).Count())
				|| (c == 0 && dialogs.Where(d => d.Initial == su).FirstOrDefault() == null)
				|| (c == 0 && Transition.GetLink(s, su).CanNavigateBack)
				select s;
			var unconvertedInitialStates =
				from s in navigationConfiguration.States
				where s.Initial
				&& dialogs.Where(d => d.Initial == s).FirstOrDefault() == null
				select s;
			return unconvertedNavigations.FirstOrDefault() == null && unconvertedInitialStates.FirstOrDefault() == null;
		}

		internal static bool ValidateTransition(NavigationDiagram navigationConfiguration, List<Dialog> dialogs)
		{
			var invalidTransitions =
				from d in dialogs
				from s in d.States
				from t in s.Transitions
				let n = Transition.GetLink(s.State, t.To.State)
				where n == null || n.Key != t.Key
				select t;
			return invalidTransitions.FirstOrDefault() == null;
		}

		private static IEnumerable<StateWrapper> GetStateWrappersCanNavigateTo(List<Dialog> dialogs, State state, State successor)
		{
			return from sw in GetStateWrappers(dialogs, state)
				   where sw.CanNavigateTo(successor, Transition.GetLink(state, successor).Key)
				   select sw;
		}

		private static IEnumerable<StateWrapper> GetStateWrappers(List<Dialog> dialogs, State state)
		{
			return (
				from d in dialogs
				from s in d.States
				where s.State == state
				select s
			);
		}
	}
}
